package com.dap.utils;

import com.google.common.base.Charsets;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.concurrent.TimeUnit;


/**
 * HttpClient操作的实现
 * Created by wm on 2017/9/20.
 */
public class MyHttpClient {
    private static final Logger logger = LoggerFactory.getLogger(MyHttpClient.class);

    protected HttpClientConnectionManager connManager;
    protected CloseableHttpClient httpClient;

    private void init(int timeoutMinutes) {
        if (timeoutMinutes <= 0 || timeoutMinutes > 1000)
            timeoutMinutes = 1;

        connManager = new PoolingHttpClientConnectionManager(timeoutMinutes*2, TimeUnit.MINUTES);

        httpClient = HttpClients.custom()
                .setConnectionTimeToLive(timeoutMinutes, TimeUnit.MINUTES)
                .setConnectionManager(connManager)
                .build();
    }

    public MyHttpClient() {
        init(1);
    }

    public MyHttpClient(int timeoutMinutes) {
        init(timeoutMinutes);
    }

    // 关闭连接,释放资源
    public void close() {
        try {
            connManager.shutdown();
        } catch (Exception e) {
            logger.warn("", e);
        }
    }

    protected void addDefaultHeader(HttpRequestBase httpRequestBase) {
        httpRequestBase.addHeader("Connection", "keep-alive");
        httpRequestBase.addHeader("Accept-Charset", "utf-8");
    }

    /**
     * 发送 post请求
     */
    public String post(final String uri, final List<NameValuePair> params) {
        HttpPost httpRequestBase = new HttpPost(uri);
        try {
            HttpEntity he = postResultHttpEntity(httpRequestBase, params);
            if (he != null) {
                try {
                    return EntityUtils.toString(he, Charsets.UTF_8);
                } catch (Exception e) {
                    logger.info("", e);
                }
            }
        } finally {
            httpRequestBase.releaseConnection();
        }

        return null;
    }


    public byte[] postBytesResult(final String uri, final List<NameValuePair> params) {
        HttpPost httpRequestBase = new HttpPost(uri);
        try {
            HttpEntity he = postResultHttpEntity(httpRequestBase, params);
            if (he != null) {
                try {
                    return EntityUtils.toByteArray(he);
                } catch (Exception e) {
                    logger.info("", e);
                }
            }
        } finally {
            httpRequestBase.releaseConnection();
        }

        return null;
    }
    public byte[] postBytesResult(final String uri, final byte[] bytesContent, ContentType contentType) {
        HttpPost httpRequestBase = new HttpPost(uri);
        try {
            HttpEntity he = postResultHttpEntity(httpRequestBase, new ByteArrayEntity(bytesContent, contentType));
            if (he != null) {
                try {
                    return EntityUtils.toByteArray(he);
                } catch (Exception e) {
                    logger.info("", e);
                }
            }
        } finally {
            httpRequestBase.releaseConnection();
        }

        return null;
    }

    public HttpEntity postResultHttpEntity(HttpPost httpRequestBase, HttpEntity entity) {
        try {
            addDefaultHeader(httpRequestBase);
            httpRequestBase.setProtocolVersion(HttpVersion.HTTP_1_1);
            httpRequestBase.addHeader("Content-Type", entity.getContentType().getValue());

            httpRequestBase.setEntity(entity);

            logger.debug("staring POST " + httpRequestBase.getURI());
            HttpResponse response = httpClient.execute(httpRequestBase);
            logger.debug("end POST --------------------");

            return response.getEntity();
        } catch (Exception e) {
            logger.info("", e);
        }

        return null;
    }


    public HttpEntity postResultHttpEntity(HttpPost httpRequestBase, final List<NameValuePair> params) {
        try {
            addDefaultHeader(httpRequestBase);
            httpRequestBase.setProtocolVersion(HttpVersion.HTTP_1_1);
            httpRequestBase.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");

            httpRequestBase.setEntity(new UrlEncodedFormEntity(params, Charsets.UTF_8));


            logger.debug("staring POST " + httpRequestBase.getURI());
            HttpResponse response = httpClient.execute(httpRequestBase);
            logger.debug("end POST --------------------");

            return response.getEntity();
        } catch (Exception e) {
            logger.info("", e);
        }

        return null;
    }

    /**
     * 发送 get请求
     */
    public String get(final String uri) {
        HttpRequestBase httpRequestBase = new HttpGet(uri);
        try {
            HttpEntity he = getResultHttpEntity(httpRequestBase);
            if (he != null) {
                try {
                    return EntityUtils.toString(he, Charsets.UTF_8);
                } catch (Exception e) {
                    logger.info("", e);
                }
            }
        } finally {
            httpRequestBase.releaseConnection();
        }

        return null;
    }

    protected HttpEntity getResultHttpEntity(HttpRequestBase httpRequestBase) {
        try {
            addDefaultHeader(httpRequestBase);
            httpRequestBase.setProtocolVersion(HttpVersion.HTTP_1_1);

            logger.debug("starting GET " + httpRequestBase.getURI());
            HttpResponse response = httpClient.execute(httpRequestBase);
            logger.debug("end GET --------------------");

            return response.getEntity();
        } catch (Exception e) {
            logger.info("", e);
        }

        return null;
    }

    protected HttpEntity putResultHttpEntity(HttpPut httpRequestBase, final byte[] content) {
        try {
            addDefaultHeader(httpRequestBase);
            httpRequestBase.setProtocolVersion(HttpVersion.HTTP_1_1);
            httpRequestBase.addHeader("Content-Type", "text/plain; charset=UTF-8");

            httpRequestBase.setEntity(new ByteArrayEntity(content, ContentType.TEXT_PLAIN));

            logger.debug("staring PUT " + httpRequestBase.getURI());
            HttpResponse response = httpClient.execute(httpRequestBase);
            logger.debug("end PUT --------------------");

            return response.getEntity();
        } catch (Exception e) {
            logger.info("", e);
        }

        return null;
    }
    /**
     * 发送 put 请求
     */
    public String put(final String uri, final byte[] content) {
        HttpPut httpRequestBase = new HttpPut(uri);
        try {
            HttpEntity he = putResultHttpEntity(httpRequestBase, content);
            if (he != null) {
                try {
                    return EntityUtils.toString(he, Charsets.UTF_8);
                } catch (Exception e) {
                    logger.info("", e);
                }
            }
        } finally {
            httpRequestBase.releaseConnection();
        }

        return null;
    }

    // 下载文件
    public boolean downloadFile(final String uri, final String fileSavePath) {
        HttpRequestBase httpRequestBase = new HttpGet(uri);
        try {
            addDefaultHeader(httpRequestBase);
            httpRequestBase.setProtocolVersion(HttpVersion.HTTP_1_1);

            logger.debug("downloading file from url\n" + httpRequestBase.getURI() + "\nsaving to\n" + fileSavePath);

            HttpResponse response = httpClient.execute(httpRequestBase);
            HttpEntity he = response.getEntity();

            OutputStream outputStream = new FileOutputStream(fileSavePath);
            he.writeTo(outputStream);
            outputStream.close();

            logger.debug("download file success --------------------");

            return true;
        } catch (Exception e) {
            logger.info("", e);
            return false;
        } finally {
            httpRequestBase.releaseConnection();
        }
    }
}
